/**
 * @file fs.h
 * @author lcz (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2022-11-02
 *
 * @copyright Copyright (c) 2022
 *
 */

#ifndef FS_H
#define FS_H

#include <sys/stat.h>
#include "fs/file.h"
#include "tools/list.h"
#include "ipc/mutex.h"
#include "fs/fatfs/fatfs.h"
#include "applib/lib_syscall.h"
// struct _fat_t;
struct stat;
struct _fs_t;
#define FS_MOUNTP_SIZE 512

typedef enum _fs_type_t
{
    FS_DEVFS,
    FS_FAT16,
} fs_type_t;

typedef struct _fs_op_t
{
    // 挂载方法
    int (*mount)(struct _fs_t *fs, int major, int minor);
    void (*unmount)(struct _fs_t *fs, int major, int minor);
    // 所有设备放在设备文件系统中进行管理
    int (*open)(struct _fs_t *fs, const char *path, file_t *file);
    // 打开的时候传一个file结构，描述一个特定的打开文件,我们将fs_t 的信息放在file结构中
    int (*read)(char *buf, int size, file_t *file);
    int (*write)(char *buf, int size, file_t *file);
    void (*close)(file_t *file);
    int (*seek)(file_t *file, uint32_t offset, int dir);
    int (*stat)(file_t *file, struct stat *st);
    // 每一种文件系统的遍历方式不太一样，我们要针对特定的文件系统写特定的遍历接口
    int (*opendir)(struct _fs_t *fs, const char *name, DIR *dir);
    int (*readdir)(struct _fs_t *fs, DIR *dir, struct dirent *dirent);
    int (*closedir)(struct _fs_t *fs, DIR *fir);
    int (*ioctl)(file_t *file, int cmd, int arg0, int arg1);
    int (*unlink)(struct _fs_t *fs,char * path);
} fs_op_t;
// 后面修改，sys_open 转换成对特定的文件系统的使用，操作，对特定文件不会直接调用函数，要做成通用的函数接口

// 具体的文件系统
typedef struct _fs_t
{
    // 具体文件的打开方式,指向回调函数表
    fs_op_t *op;
    // 挂载点
    char mount_point[FS_MOUNTP_SIZE];

    fs_type_t type;
    // 临时保存数据
    void *data;
    // 对应磁盘文件，分区
    int dev_id;
    list_node_t node;
    mutex_t *mutex; // 文件系统操作互斥信号量
    // 目前暂时这样设计，可能看起来不好，但是是最简单的方法
    // 这样就不用考虑内存分配的问题
    union
    {
        fat_t fat_data; // 文件系统相关数据
    };
} fs_t;

int sys_open(const char *name, int flags, ...);
int sys_read(int file, char *ptr, int len);
int sys_write(int file, char *ptr, int len);
int sys_lseek(int file, int ptr, int dir);
int sys_close(int file);

int sys_isatty(int file);

int sys_fstat(int file, struct stat *st);

void fs_init(void);
int sys_dup(int file);

int path_to_num(const char *path, int *num);
const char *path_next_child(const char *path);

int sys_opendir(const char *name, DIR *dir);
int sys_readdir(DIR *dir, struct dirent *dirent);
int sys_closedir(DIR *dir);

int sys_ioctl(int fd, int cmd, int arg0, int arg1);
int sys_unlink(const char * path);

#endif /* FS_H */
